﻿using MCUPackage;
using MCUPackage.Utils;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;

namespace SxPackages.STC32G.Models
{
	[Serializable]
	class ZnFatOptions
	{
		protected STC32GQFP64 mParent = null;

		[Category("ZnFat"),
		DisplayName("使能"),
		DefaultValue(false),
		JsonProperty(Order = 100),
		Description("是否使能ZnFat文件系统")]
		public bool Enable { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能格式化功能"),
		DefaultValue(true),
		Description("是否使能文件系统格式化功能")]
		public bool EnableFormat { get; set; } = true;

		[Category("ZnFat"),
		DisplayName("使能读取文件功能"),
		DefaultValue(true),
		Description("是否使能读取文件功能")]
		public bool EnableRdFile { get; set; } = true;

		[Category("ZnFat"),
		DisplayName("使能高级读取文件功能"),
		DefaultValue(false),
		Description("是否使能高级读取文件功能, 此功能会将读取的每个字节送到处理函数，处理函数由使用者提供")]
		public bool EnableExRdFile { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能创建文件功能"),
		DefaultValue(true),
		Description("是否使能创建文件功能")]
		public bool EnableCreateFile { get; set; } = true;

		[Category("ZnFat"),
		DisplayName("使能删除文件功能"),
		DefaultValue(true),
		Description("是否使能删除文件功能")]
		public bool EnableRemoveFile { get; set; } = true;

		[Category("ZnFat"),
		DisplayName("使能写入文件功能"),
		DefaultValue(true),
		Description("是否使能写入文件功能, 写入数据均是从文件的末尾追加数据")]
		public bool EnableWRFile { get; set; } = true;

		[Category("ZnFat"),
		DisplayName("使能修改文件功能"),
		DefaultValue(false),
		Description("是否使能修改文件功能")]
		public bool EnableModifyFile { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能创建目录功能"),
		DefaultValue(false),
		Description("是否使能创建目录功能, 可以一次性创建多级深层目录")]
		public bool EnableCreateDir { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能删除目录功能"),
		DefaultValue(false),
		Description("是否使能删除目录功能, 目录下有子目录和文件, 以及树状子目录结构, 也可一并全部删除")]
		public bool EnableRemoveDir { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能文件数据截断功能"),
		DefaultValue(false),
		Description("是否使能文件数据截断功能, 从文件的某个位置之后的数据全部删除")]
		public bool EnableDump { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能文件数据定位功能"),
		DefaultValue(false),
		Description("是否使能文件数据定位功能")]
		public bool EnableSeek { get; set; } = false;

		private bool mEnableLongName = false;
		[Category("ZnFat"),
		DisplayName("使能长文件名功能"),
		DefaultValue(false),
		Description("是否使能长文件名功能, 在长文件名下需要使用到较多的RAM资源")]
		public bool EnableLongName
		{
			get => mEnableLongName;
			set
			{
				if (value != mEnableLongName)
				{
					mEnableLongName = value;
					if (!value)
					{
						// 禁用时其他依赖功能统一禁用
						EnableChinese = value;
					}
				}
			}
		}

		private bool mEnableChinese = false;
		[Category("ZnFat"),
		DisplayName("使能长文件名中文功能"),
		DefaultValue(false),
		Description("是否使能长文件名中文功能, 在长文件名中是否包含中文字符")]
		public bool EnableChinese
		{
			get => mEnableChinese;
			set
			{
				if (value != mEnableChinese)
				{
					if (value && !EnableLongName)
					{
						return;
					}
					mEnableChinese = value;
				}
			}
		}

		private int mLongNameSize = 50;
		[Category("ZnFat"),
		DisplayName("长文件名长度上限"),
		DefaultValue(50),
		Description("长文件名是unicode编码, 两个字节表示一个字符, 所以实际占用的内存为文件名长度*2, 取值范围10~127")]
		public int LongNameSize
		{
			get => mLongNameSize;
			set
			{
				if (value != mLongNameSize)
				{
					if (value < 10 || value > 127)
					{
						return;
					}
					mLongNameSize = value;
				}
			}
		}

		private bool mEnableFlushInfo = true;
		[Category("ZnFat"),
		DisplayName("使能实时更新扇区功能"),
		DefaultValue(true),
		Description("是否使能实时更新扇区功能, 主要是更新剩余簇数")]
		public bool EnableFlushInfo
		{
			get => mEnableFlushInfo;
			set
			{
				if (value != mEnableFlushInfo)
				{
					mEnableFlushInfo = value;
					if (!value)
					{
						// 关闭本功能则必须开启刷新函数
						EnableFlush = true;
					}
				}
			}
		}

		[Category("ZnFat"),
		DisplayName("使能刷新文件系统功能"),
		DefaultValue(false),
		Description("是否使能刷新文件系统功能, 如果没有开启实时更新FSINFO扇区功能则需要开启此功能")]
		public bool EnableFlush { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能实时更新文件信息功能"),
		DefaultValue(false),
		Description("是否使能实时更新文件信息功能, 如果实时更新扇区与本功能都禁用, 则在文件操作结束后一定要调用关闭文件接口, 否则磁盘相关信息将不会被更新")]
		public bool EnableFlushSize { get; set; } = false;

		[Category("ZnFat"),
		DisplayName("使能实时更新FAT簇链功能"),
		DefaultValue(true),
		Description("是否实时更新FAT簇链，不实时更新，则使用CCCB簇链缓冲，可以加快数据写入速度, 弊端在于缓冲中的簇链不会写到物理扇区中，会造成数据丢失，因此要及时回写")]
		public bool EnableUpdateCluster { get; set; } = true;

		/// <summary>
		/// 生成项目文档
		/// </summary>
		/// <param name="aPath"></param>
		/// <returns></returns>
		public bool Generate(string aPath)
		{
			if (!this.Enable)
			{
				return false;
			}

			string tmpFile = "FatConfig.h";
			string srcPath = Path.Combine(mParent.TemplatePath, PrjPathTypes.Middlewares_ZnFat.ToDescription());
			if (!Directory.Exists(srcPath))
			{
				return false;
			}
			string dstPath = Path.Combine(aPath, PrjPathTypes.Middlewares_ZnFat.ToDescription());

			// 复制文件到目标目录
			string[] files = Directory.GetFiles(srcPath);
			if (files == null || files.Length < 1)
			{
				return false;
			}
			Directory.CreateDirectory(dstPath);
			foreach (var file in files)
			{
				if (!file.EndsWith(tmpFile, StringComparison.CurrentCultureIgnoreCase))
				{
					// 模板文件不复制
					PrjTemplate.Append(PrjPathTypes.Middlewares_ZnFat, Path.GetFileName(file));
					File.Copy(file, Path.Combine(dstPath, Path.GetFileName(file)), true);
				}
			}

			var pairs = TemplateHelper.CreatePairs();
			Type type = this.GetType();
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
			string head = "Enable";
			foreach (var property in properties)
			{
				if (property.Name.StartsWith(head) && !property.Name.Equals(head))
				{
					pairs.EnableKey(property.Name.Substring(head.Length), (bool)property.GetValue(this));
				}
			}
			pairs["LongNameSize"] = this.LongNameSize.ToString();
			return mParent.CreateByTemplate(PrjPathTypes.Middlewares_ZnFat, aPath, tmpFile, true, pairs, "ZnFat配置接口");
		}

		public ZnFatOptions(STC32GQFP64 aParent)
		{
			this.mParent = aParent;
		}
	}
}
